package dao;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import externaldata.passageTrainTheorique.PassageTrainTheorique;


public class DaoPassageTrainTheorique {
	
	/* ------------------------------------------------ REQUETES PRECOMPILEES */
	private static CallableStatement statementAjouterListe = null;
	private static CallableStatement statementGetAll = null;
	private static CallableStatement statementGetOne = null;
	private static CallableStatement statementGetOneById = null;
	private static CallableStatement statementUpdateOne = null;
	private static CallableStatement statementDeleteOne = null;
	private static CallableStatement statementValiderTrainEnGare = null;
	private static CallableStatement statementValiderDefis = null;
	
	
	static {
		
		try {
			statementAjouterListe = DbConnection.getInstance().prepareCall(
					"{call createPassageTrainTheorique(?, ?, ?, ?, ?, ?, ?)}");
			
			statementGetOneById = DbConnection.getInstance().prepareCall(
					"{call getPassageTrainTheoriqueById(?)}");

			statementGetOne = DbConnection.getInstance().prepareCall(
					"{call getPassageTrainTheorique(?, ?, ?, ?)}");

			statementGetAll = DbConnection.getInstance().prepareCall(
					"{call getAllPassageTrainTheorique()}");

			statementUpdateOne = DbConnection.getInstance().prepareCall(
					"{call updatePassageTrainTheorique(?, ?, ?)}");
			
			statementDeleteOne = DbConnection.getInstance().prepareCall(
					"{call deletePassageTrainTheorique(?)}");
			
			statementValiderTrainEnGare = DbConnection.getInstance().prepareCall(
					"{call validePariSurTrainTheorique(?, ?)}");
			
			statementValiderDefis = DbConnection.getInstance().prepareCall(
					"{call validerDefis()}");
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	

	
	/* -------------------------------------------------- METHODES D'ACCES BD */
	
	public static void ajouterListe(List<PassageTrainTheorique> pttListe) {
		
		for (PassageTrainTheorique ptt : pttListe) {
			
			try {
				synchronized (statementAjouterListe) {
					// Ajout des paramètres
					
					// Arrivee
					statementAjouterListe.setTimestamp(1, new java.sql.Timestamp(ptt.getArriveeTheorique().getTime()));
					// DestinationUic
					statementAjouterListe.setString(2, ptt.getDestinationUic());
					// AUnPari
					statementAjouterListe.setBoolean(3, ptt.getAUnPari());
					// NumeroTrain
					statementAjouterListe.setString(4, ptt.getNumeroTrain());
					// GareDua
					statementAjouterListe.setString(5, ptt.getGareDua());
					// NomTrain
					statementAjouterListe.setString(6, ptt.getNomTrain());
					// ReseauTrain
					statementAjouterListe.setString(7, ptt.getReseauTrain());
					
					
					// Exécution
					statementAjouterListe.execute();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static PassageTrainTheorique getPassageTrainTheorique(int id_passageTrainTheorique) {
		
		PassageTrainTheorique passageTrainTheorique = null;
		
		try {
			ResultSet rs = null;
			
			synchronized (statementGetOneById) {
				statementGetOneById.setInt(1, id_passageTrainTheorique);
				
				rs = statementGetOneById.executeQuery();
			}
			
			if (rs != null) {
				if(rs.last()) {
					if(rs.getRow() == 1) {
						passageTrainTheorique = new PassageTrainTheorique(
								rs.getInt("id_passageTrainTheorique"),
								rs.getString("numeroTrain"),
								rs.getString("nomTrain"),
								rs.getString("gareDua"),
								rs.getString("destinationUic"),
								rs.getTimestamp("arriveeTheorique"),
								rs.getBoolean("aUnPari"),
								rs.getString("reseauTrain"));
					}
					else {
						System.err.println("DaoPassageTrainTheorique.getPassageTrainTheorique(" + id_passageTrainTheorique + ") : plusieurs résultats.");
					}
				}
				else {
					System.out.println("DaoPassageTrainTheorique.getPassageTrainTheorique(" + id_passageTrainTheorique + ") : aucun résultat.");
				}
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return passageTrainTheorique;
	}
	
	public static PassageTrainTheorique getOne(String numeroTrain, String gareDua, Date passageReel) {
		
		PassageTrainTheorique passage = null;

		try {
			ResultSet rs = null;
			

			// Recherche du train correspondant dans une fourchette de -10h +10h
			
			Calendar cal = new GregorianCalendar();
			
	        cal.setTime(passageReel);
	        cal.add(Calendar.HOUR, -10);
			Date debutFourchetteHoraire = cal.getTime();
			
			cal.setTime(passageReel);
	        cal.add(Calendar.HOUR, 10);
			Date finFourchetteHoraire = cal.getTime();
			
			synchronized (statementGetOne) {
				// Ajout des paramètres
				
				// numTrain
				statementGetOne.setString(1, numeroTrain);
				// gareDua
				statementGetOne.setString(2, gareDua);
				// debutFourchetteHoraire
				statementGetOne.setTimestamp(3, new java.sql.Timestamp(debutFourchetteHoraire.getTime()));
				// finFourchetteHoraire
				statementGetOne.setTimestamp(4, new java.sql.Timestamp(finFourchetteHoraire.getTime()));
				
				
				// Exécution
				rs = statementGetOne.executeQuery();
			}
			
			if (rs != null && rs.last()) {
				if (rs.getRow() == 1) {
					
					passage = new PassageTrainTheorique(
							rs.getInt("id_passageTrainTheorique"),
							rs.getString("numeroTrain"),
							rs.getString("nomTrain"),
							rs.getString("gareDua"),
							rs.getString("destinationUic"),
							rs.getTimestamp("arriveeTheorique"),
							rs.getBoolean("aUnPari"),
							rs.getString("reseauTrain"));
				}
				else {
					System.err.println("DaoPassageTrainTheorique.getOne(" + numeroTrain + ", " + gareDua + ") : plusieurs résultats.");
				}
			}
			else {
				System.out.println("DaoPassageTrainTheorique.getOne(" + numeroTrain + ", " + gareDua + ") : aucun résultat.");
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return passage;
	}
	
	public static List<PassageTrainTheorique> getAll() {
		
		List<PassageTrainTheorique> passages = null;
		
		try {
			ResultSet rs = null;
			
			synchronized (statementGetAll) {
				// Exécution
				rs = statementGetAll.executeQuery();
			}
			
			if (rs != null) {
				passages = new ArrayList<PassageTrainTheorique>();
				
				while (rs.next()) {
					passages.add(new PassageTrainTheorique(
							rs.getInt("id_passageTrainTheorique"),
							rs.getString("numeroTrain"),
							rs.getString("nomTrain"),
							rs.getString("gareDua"),
							rs.getString("destinationUic"),
							rs.getTimestamp("arriveeTheorique"),
							rs.getBoolean("aUnPari"),
							rs.getString("reseauTrain")));
				}
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return passages;
	}
	
	public static void updateOne(PassageTrainTheorique ptt) {
		
		try {
			synchronized (statementUpdateOne) {
				// Ajout des paramètres
				
				// Id
				statementUpdateOne.setInt(1, ptt.getId());
				// DestinationUic
				statementUpdateOne.setString(2, ptt.getDestinationUic());
				// NomTrain
				statementUpdateOne.setString(3, ptt.getNomTrain());
				
				
				// Exécution
				statementUpdateOne.execute();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public static void supprimerListe(List<PassageTrainTheorique> pttListe) {
		
		for (PassageTrainTheorique ptt : pttListe) {
			
			try {
				synchronized (statementDeleteOne) {
					// Ajout des paramètres
					
					// Id
					statementDeleteOne.setInt(1, ptt.getId());
	
					
					// Exécution
					statementDeleteOne.execute();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void deleteOne(PassageTrainTheorique ptt) {
		try {
			synchronized (statementDeleteOne) {
				// Ajout des paramètres
				
				// Id
				statementDeleteOne.setInt(1, ptt.getId());

				
				// Exécution
				statementDeleteOne.execute();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	public static void validerTrainEnGare(PassageTrainTheorique ptt, int retardMinutes) {
		
		try {
			
			System.out.println("Train en gare : " 
							+ "\n\tId : " + ptt.getId()
							+ ", Numero : " + ptt.getNumeroTrain()
							+ ", Nom : " + ptt.getNomTrain()
							+ ", Reseau : " + ptt.getReseauTrain()
							+ ", A un pari (selon BD) : " + ptt.getAUnPari()
							+ ", Retard calculé (min) : " + retardMinutes);
			
			synchronized (statementValiderTrainEnGare) {
				// Ajout des paramètres
				
				// Id PassageTrainTheorique
				statementValiderTrainEnGare.setInt(1, ptt.getId());
				// Nombre de minutes
				statementValiderTrainEnGare.setInt(2, retardMinutes);
				
				
				// Exécution
				statementValiderTrainEnGare.execute();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
	}
	
	public static void validerDefis() {
		
		try {
			statementValiderDefis.execute();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}
